﻿using System;
using System.Configuration;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using MySql.Data.MySqlClient;
using FindIt.BLL;
using System.Drawing;
using FindIt.DAL;

namespace FindIt.UI.Pages
{
    public partial class Upload : System.Web.UI.Page
    {
        private string imagesFolder = ConfigurationManager.AppSettings["imagesFolder"];
        private string webPagesFolder = ConfigurationManager.AppSettings["webPagesFolder"];
        private string resourcesFolder = ConfigurationManager.AppSettings["resourcesFolder"];
        private enum FileType { webPage, image, unrecognized };
        
        protected void Page_Load(object sender, EventArgs e)
        {
        }


        protected void btnUpload_Click(object sender, EventArgs e)
        {
            if (fuFile.HasFile)
            {
                string title = txtTitle.Text;

                if (title == "")
                {
                    lblUploadStatus.ForeColor = Color.Red;
                    lblUploadStatus.Text = "Please enter a title for your file.";
                }
                
                else if (ContainsStopWord(title))
                {
                    lblUploadStatus.ForeColor = Color.Red;
                    lblUploadStatus.Text = "Could not upload file. Your title contains a stop word";
                }

                else if (txtKeyword1.Text == "" && txtKeyword2.Text == "" && txtKeyword3.Text == "")
                {
                    lblUploadStatus.ForeColor = Color.Red;
                    lblUploadStatus.Text = "Please enter atleast one keyword for your file.";
                }

                else if (ContainsStopWord(txtKeyword1.Text) || ContainsStopWord(txtKeyword1.Text) || ContainsStopWord(txtKeyword1.Text))
                {
                    lblUploadStatus.ForeColor = Color.Red;
                    lblUploadStatus.Text = "Could not upload file. Your keywords contain a stop word.";
                }

                else
                {
                    try
                    {
                        FileType fileType = GetFileType(fuFile.PostedFile.ContentType);
                        int fileSize = fuFile.PostedFile.ContentLength;
                        int maxFileSize = int.Parse(ConfigurationManager.AppSettings["maxFileSize"]);
                        int maxNumWebPageKeywords = int.Parse(ConfigurationManager.AppSettings["maxNumWebPageKeywords"]);
                        int maxNumImageKeywords = int.Parse(ConfigurationManager.AppSettings["maxNumImageKeywords"]);

                        string uploadStatusMessage = "";
                        Color uploadStatusColor;

                        if (fileType == FileType.unrecognized)
                        {
                            uploadStatusColor = Color.Red;
                            uploadStatusMessage = "The file could not be uploaded. The file format is not supported";
                        }

                        else if (fileSize > maxFileSize)
                        {
                            uploadStatusColor = Color.Red;
                            uploadStatusMessage = "The file could not be uploaded. The file has to be less than " + (maxFileSize / 1024) / 1024 + " mb!";
                        }

                        else
                        {
                            if (fileType == FileType.webPage)
                            {
                                string savePath = Server.MapPath("~/" + ConfigurationManager.AppSettings["webPagesFolder"] + "/");
                                string savedFileName = SaveFile(savePath, ref uploadStatusMessage);
                                string savedFilePath = savePath + savedFileName;

                                int remainingKeywords = maxNumWebPageKeywords;
                                Dictionary<string, int> userProvidedKeywords = GetUserProvidedWebPageKeywords(ref remainingKeywords);
                                Dictionary<string, int> systemGeneratedKeywords = new Dictionary<string, int>();

                                if (!WebPage.GenerateKeywords(savedFilePath, ref systemGeneratedKeywords, userProvidedKeywords, remainingKeywords))
                                {
                                    File.Delete(savedFilePath);
                                    uploadStatusColor = Color.Red;
                                    uploadStatusMessage = "The file could not be uploaded. The file has a stop word";
                                }

                                else
                                {
                                    uploadStatusColor = Color.Black;
                                    Dictionary<string, int> keywords = userProvidedKeywords.Concat(systemGeneratedKeywords).ToDictionary(x => x.Key, x => x.Value);
                                    WebPage webPage = new WebPage(txtTitle.Text, savedFileName, fileSize, cbProtected.Checked, DateTime.Now, DateTime.Now, 0, 0,
                                                                  DateTime.MinValue, WebPage.StatusType.normal, "Owner", keywords);
                                    webPage.AddWebPageToDB();
                                }
                            }

                            else if (fileType == FileType.image)
                            {

                                string savePath = Server.MapPath("~/" + ConfigurationManager.AppSettings["imagesFolder"] + "/");
                                string savedFileName = SaveFile(savePath, ref uploadStatusMessage);
                                string savedFilePath = savePath + savedFileName;

                                HashSet<string> userProvidedKeywords = GetUserProvidedImageKeywords();

                                uploadStatusColor = Color.Black;
                                FindIt.BLL.Image image = new FindIt.BLL.Image(txtTitle.Text, savedFileName, fileSize, cbProtected.Checked, DateTime.Now, DateTime.Now, 0,
                                                                    DateTime.MinValue, FindIt.BLL.Image.StatusType.normal, "Owner", userProvidedKeywords);
                                    
                                image.AddImageToDB();
                            }
                        }

                        lblUploadStatus.Text = uploadStatusMessage;
                    }

                    catch (Exception ex)
                    {
                        lblUploadStatus.ForeColor = Color.Red;
                        lblUploadStatus.Text = "The file could not be uploaded. The following error occured: " + ex.Message;
                    }
                }
            }

            else
            {
                lblUploadStatus.ForeColor = Color.Red;
                lblUploadStatus.Text = "Please specify a file to upload";
            }
        }
        

        private FileType GetFileType(string mime)
        {
            switch (mime)
            {
                case "text/html":
                    return FileType.webPage;

                case "image/jpeg":
                    return FileType.image;

                case "image/bmp":
                    return FileType.image;
                
                case "image/png":
                    return FileType.image;

                case "image/gif":
                    return FileType.image;

                default:
                    return FileType.unrecognized;
            }
        }

        private string SaveFile(string savePath, ref string uploadStatusMessage)
        {
            string clientFileName = fuFile.FileName;
            string saveFileName = clientFileName;
            string pathToCheck = savePath + saveFileName;
            

            if (System.IO.File.Exists(pathToCheck))
            {
                int counter = 1;

                while (System.IO.File.Exists(pathToCheck))
                {
                    saveFileName = counter.ToString() + clientFileName;
                    pathToCheck = savePath + saveFileName;
                    counter++;
                }

                uploadStatusMessage = "A file with the same name already exists." +
                                      "<br />Your file was saved as " + saveFileName;
            }

            else
            {
                uploadStatusMessage = "Your file was uploaded successfully!";
                
            }

            fuFile.SaveAs(savePath + saveFileName);
            return saveFileName;
        }

        private Dictionary<string, int> GetUserProvidedWebPageKeywords(ref int remainingKeywords)
        {
            Dictionary<string, int> keywords = new Dictionary<string,int>();

            if (txtKeyword1.Text != "")
            {
                string key = StemWord(txtKeyword1.Text);
                keywords.Add(key, -1);
                remainingKeywords--;
            }

            if (txtKeyword2.Text != "")
            {
                string key = StemWord(txtKeyword2.Text);
                if (!keywords.ContainsKey(key))
                {
                    keywords.Add(key, -1);
                    remainingKeywords--;
                }
            }

            if (txtKeyword3.Text != "")
            {
                string key = StemWord(txtKeyword3.Text);
                if (!keywords.ContainsKey(key))
                {
                    keywords.Add(key, -1);
                    remainingKeywords--;
                }
            }

            return keywords;
        }

        private HashSet<string> GetUserProvidedImageKeywords()
        {
            HashSet<string> keywords = new HashSet<string>();

            if (txtKeyword1.Text != "")
            {
                string key = StemWord(txtKeyword1.Text);
                keywords.Add(key);
            }

            if (txtKeyword2.Text != "")
            {
                string key = StemWord(txtKeyword2.Text);
                if (!keywords.Contains(key))
                {
                    keywords.Add(key);
                }
            }

            if (txtKeyword3.Text != "")
            {
                string key = StemWord(txtKeyword3.Text);
                if (!keywords.Contains(key))
                {
                    keywords.Add(key);
                }
            }

            return keywords;
        }
        
        private string StemWord(string key)
        {
            PorterStemmer stemmer = new PorterStemmer();
            return stemmer.stemTerm(key).ToLower();
        }

        private bool ContainsStopWord(string text)
        {
            Regex regex = new Regex(@"\s+");
            string[] parts = regex.Split(text);

            foreach (string part in parts)
            {
                if (RestrictedWord.IsStopWord(part))
                    return true;
            }

            return false;
        }
    }
}
